package cn.wolfcode.web.controller;

import cn.wolfcode.common.CheckUtils;
import cn.wolfcode.common.constants.CommonConstants;
import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.OrderInfo;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.RedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.UserUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by lanxw
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
    @Autowired
    private ISeckillProductService seckillProductService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private IOrderInfoService orderInfoService;

    public static ConcurrentHashMap<Long, Boolean> STOCK_OVER_MAP = new ConcurrentHashMap<>();

    @RequestMapping("/doSeckill")
    @RequireLogin
    public Result<String> doSeckill(Integer time, Long seckillId, HttpServletRequest request) {
        CheckUtils.notNull(time);
        CheckUtils.notNull(seckillId);

        // 判断本地标记.
        Boolean isOver = STOCK_OVER_MAP.get(seckillId);
        if (isOver != null && isOver) {
            // 本地标识中,对应秒杀场次的秒杀商品ID的值为true,说明redis中库存已经减成负数,没有库存了
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        SeckillProductVo seckillProductVo = seckillProductService.find(time, seckillId);
        if (seckillProductVo == null) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_NOT_EXIST);
        }

        String token = request.getHeader(CommonConstants.TOKEN_NAME);
        UserInfo userInfo = UserUtil.getUser(redisTemplate, token);
        if (redisTemplate.opsForHash().hasKey(RedisKey.SECKILL_ORDER_HASH.getRealKey(time + ""), seckillId + ":" + userInfo.getPhone())) {
            // 说明已经抢购过了.
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }

        Long count = redisTemplate.opsForHash().increment(RedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + ""), seckillId + "", -1L);
        if (count < 0) {
            // 设置本地标识
            STOCK_OVER_MAP.put(seckillId, true);
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }


        OrderMessage orderMessage = new OrderMessage(time, seckillId, token, userInfo.getPhone());
        rocketMQTemplate.syncSend(MQConstant.ORDER_PEDDING_TOPIC, orderMessage);
        return Result.success("进入队列成功，请等待结果.", null);
    }

    @RequestMapping("/find")
    @RequireLogin
    public Result<OrderInfo> find(String orderNo, HttpServletRequest request) {
        CheckUtils.notNull(orderNo);

        String token = request.getHeader(CommonConstants.TOKEN_NAME);
        UserInfo userInfo = UserUtil.getUser(redisTemplate, token);
        OrderInfo orderInfo = orderInfoService.find(orderNo);

        // 1.只能访问自己的订单
        if (orderInfo == null || !orderInfo.getUserId().equals(userInfo.getPhone())) {
            // 说明订单号码有问题，在数据库中无法查询到
            throw new BusinessException(SeckillCodeMsg.ORDER_NOT_EXIST);
        }

        return Result.success(orderInfo);
    }
}
